using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using Magiq.Support;
using Magiq.Support.Database;

namespace Magiq.Sql {
    public class TableVariableDependentUpdateStrategy : IDependentTablesUpdateStrategy {
        #region IDependentTablesUpdateStrategy Members

        public int Execute<T>(MassUpdate<T> massUpdate, IEnumerable<TableUpdate<T>> tableUpdates) where T : class {
            var dataContext = massUpdate.DataContext;
            var tableVars = new List<string>();
            var columns = new List<string>();
            var values = new List<string>();
            //var q = new DeleteExecutor(massUpdate.)
            var assignmentBuilder = new QueryColumnAssignmentBuilder(dataContext);
            var dataProvider = new SqlDatabaseAdapter(dataContext);
            var query = new DeleteExecutor(dataProvider, massUpdate.Update.Where);

            foreach (var tableUpdate in tableUpdates) {
                var samplePropertySet = tableUpdate.PropertySets.First();
                var tableType = samplePropertySet.DeclaringType;
                var table = dataContext.Mapping.GetMetaType(tableType);

                foreach (var pk in table.DataMembers.Where(x => x.IsPrimaryKey)) {
                    var column = Encode(table.Table.TableName) + "_" + Encode(pk.Name);
                    tableVars.Add(column + " " + pk.SqlType());
                    columns.Add(column);

                    //obtengo el valor q iria para esta columna
                    var parameter = Expression.Parameter(typeof (T), "x");
                    var pi = (PropertyInfo) pk.Member;
                    var getPk = Expression.Property(parameter, pi);
                    var body = pi.PropertyType.IsValueType
                                   ? (Expression) Expression.Convert(getPk, typeof (object))
                                   : getPk;
                    var exp = Expression.Lambda<Func<T, object>>(body, parameter);

                    var command = dataContext.GetCommand(tableUpdate.Where.Select(exp));
                    var sqlValue = command.CommandText.From("SELECT").Until("AS").Until("FROM").Trim();
                    values.Add(sqlValue);
                }
            }

            var sqlBuilder = new StringBuilder()
                .Append("declare @table TABLE (")
                .Append(tableVars.Join(","))
                .Append(")")
                .Append("INSERT INTO @table( ")
                .Append(columns.Join(","))
                .Append(") SELECT ")
                .Append(values.Join(","))
                .Append(" FROM ")
                .Append(query.BaseWhereClause);

            //insert into @table( columnas q tengo ) select ......... from el where.
            //cada columna la hago
            return 0;
        }

        #endregion

        private static string Encode(string dbMember) {
            return dbMember.Replace("_", "__");
        }
    }
}